package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.mapper.TeachplanMapper;
import com.xuecheng.content.mapper.TeachplanMediaMapper;
import com.xuecheng.content.model.dto.BingTeachplanMediaDto;
import com.xuecheng.content.model.dto.SaveTeachplanDto;
import com.xuecheng.content.model.dto.TeachplanDto;
import com.xuecheng.content.model.po.Teachplan;
import com.xuecheng.content.model.po.TeachplanMedia;
import com.xuecheng.content.service.TeachplanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class TeachplanServiceImpl implements TeachplanService {

    @Autowired
    TeachplanMapper teachplanMapper;

    @Autowired
    TeachplanMediaMapper teachplanMediaMapper;

    @Override
    public List<TeachplanDto> findTeachplanTree(Long courseId) {
        List<TeachplanDto> teachplanDtos = teachplanMapper.selectTreeNodes(courseId);

        return teachplanDtos;
    }

    @Transactional
    @Override
    public void saveTeachplan(SaveTeachplanDto saveTeachplanDto) {
        //通过有无课程计划id判断是新增还是修改
        Long teachplanId = saveTeachplanDto.getId();
        if (teachplanId == null) {
            //新增课程
            Teachplan teachplan = new Teachplan();
            BeanUtils.copyProperties(saveTeachplanDto, teachplan);
            //确定排序字段，找到它的同级节点个数，排序字段就是个数加一 select count(1) from teachplan where course_id=117 and parentid=268
            //先获取到课程id和父节点id
            Long courseId = saveTeachplanDto.getCourseId();
            Long parentid = saveTeachplanDto.getParentid();
            int teachplanCount = getTeachplanCount(courseId, parentid);
            teachplan.setOrderby(teachplanCount);

            teachplanMapper.insert(teachplan);
        } else {
            //修改课程
            Teachplan teachplan = teachplanMapper.selectById(teachplanId);
            BeanUtils.copyProperties(saveTeachplanDto, teachplan);
            teachplanMapper.updateById(teachplan);
        }
    }

    @Transactional
    @Override
    public void deletaTeachplan(Long id) {
        if (id == null) {
            XueChengPlusException.cast("课程计划id为空");
        }

        //判断当前传来的课程id是为章节还是小节
        Teachplan teachplan = teachplanMapper.selectById(id);
        Integer grade = teachplan.getGrade();
        if (grade == 1) {
            //是章节，章节需判断章节下是否还有小节
            LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Teachplan::getParentid, id);
            Integer count = teachplanMapper.selectCount(queryWrapper);
            if (count > 0) {
                XueChengPlusException.cast("当前章节下还有小节，不可删除");
            }

            //没有小节，直接删除
            teachplanMapper.deleteById(id);

        }else {
            //是小节，小节直接删除即可
            teachplanMapper.deleteById(id);
            //但删除完小节，还应该将其媒资信息一并删除
            LambdaQueryWrapper<TeachplanMedia> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TeachplanMedia::getTeachplanId, id);
            teachplanMediaMapper.delete(queryWrapper);
        }
    }

    @Transactional
    @Override
    public void orderByTeachplan(String moveType, Long id) {
        //获得需要移动的章节
        Teachplan teachplan = teachplanMapper.selectById(id);
        //获取grade,判断其层级（章节？小节），章节移动和小节移动的处理逻辑不同
        Integer grade = teachplan.getGrade();
        //获取排序字段，方便后续操作
        Integer orderby = teachplan.getOrderby();
        //章节移动是比较同一课程下的排序字段
        Long courseId = teachplan.getCourseId();
        //小节移动是比较同一章节下的排序字段
        Long parentid = teachplan.getParentid();
        //判断移动类型
        if ("moveup".equals(moveType)) {
            //上移
            if (grade == 1) {
                //章节移动
                LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
                //查询同一课程id和同一层级下，比当前节点靠前的数据
                queryWrapper.eq(Teachplan::getGrade, grade).eq(Teachplan::getCourseId, courseId)
                        .eq(Teachplan::getOrderby, orderby - 1);
                Teachplan tmp = teachplanMapper.selectOne(queryWrapper);
                //交换排序字段
                exchangeOrderby(tmp, teachplan);
            } else if (grade == 2) {
                //小节移动
                LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
                //查询同一父节点和同一层级下，比当前节点靠前的数据
                queryWrapper.eq(Teachplan::getGrade, grade).eq(Teachplan::getParentid, parentid)
                        .eq(Teachplan::getOrderby, orderby - 1);
                Teachplan tmp = teachplanMapper.selectOne(queryWrapper);
                //交换排序字段
                exchangeOrderby(tmp, teachplan);
            }
        } else if ("movedown".equals(moveType)) {
            //下移
            if (grade == 1) {
                //章节移动
                LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
                //查询同一课程id和同一层级下，比当前节点靠前的数据
                queryWrapper.eq(Teachplan::getGrade, grade).eq(Teachplan::getCourseId, courseId)
                        .eq(Teachplan::getOrderby, orderby + 1);
                Teachplan tmp = teachplanMapper.selectOne(queryWrapper);
                //交换排序字段
                exchangeOrderby(tmp, teachplan);
            } else if (grade == 2) {
                //小节移动
                LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
                //查询同一父节点和同一层级下，比当前节点靠前的数据
                queryWrapper.eq(Teachplan::getGrade, grade).eq(Teachplan::getParentid, parentid)
                        .eq(Teachplan::getOrderby, orderby + 1);
                Teachplan tmp = teachplanMapper.selectOne(queryWrapper);
                //交换排序字段
                exchangeOrderby(tmp, teachplan);
            }
        }
    }

    @Transactional
    @Override
    public void associationMedia(BingTeachplanMediaDto bingTeachplanMediaDto) {

        String teachplanId = bingTeachplanMediaDto.getTeachplanId();
        Teachplan teachplan = teachplanMapper.selectById(teachplanId);
        if (teachplanId == null){
            XueChengPlusException.cast("课程计划不存在,课程计划名称:"+teachplan.getPname());
        }
        if (teachplan.getGrade() != 2){
            XueChengPlusException.cast("只有第二级教学计划才能绑定媒资");
        }
        //先删除原来教学计划所绑定的媒资
        teachplanMediaMapper.delete(new LambdaQueryWrapper<TeachplanMedia>()
                .eq(TeachplanMedia::getTeachplanId,teachplanId));
        TeachplanMedia teachplanMedia = new TeachplanMedia();
        teachplanMedia.setTeachplanId(Long.valueOf(bingTeachplanMediaDto.getTeachplanId()));
        teachplanMedia.setMediaId(bingTeachplanMediaDto.getMediaId());
        teachplanMedia.setCourseId(teachplan.getCourseId());
        teachplanMedia.setMediaFilename(bingTeachplanMediaDto.getFileName());
        teachplanMedia.setCreateDate(LocalDateTime.now());
        teachplanMediaMapper.insert(teachplanMedia);
    }

    /**
     * 交换排序字段
     * @param tmp
     * @param teachplan
     */
    private void exchangeOrderby(Teachplan tmp, Teachplan teachplan) {
        if (tmp == null) {
            XueChengPlusException.cast("已经到边界，无法再移动了");
        }
        //没有到边界，修改两个课程计划的排序字段
        Integer tmpOrderby = tmp.getOrderby();
        Integer orderby = teachplan.getOrderby();
        teachplan.setOrderby(tmpOrderby);
        tmp.setOrderby(orderby);
        teachplanMapper.updateById(teachplan);
        teachplanMapper.updateById(tmp);
    }

    /**
     * 获取当前课程有多少章节，或者章节下面有多少小节
     *
     * @param courseId
     * @param parentid
     * @return
     */
    private int getTeachplanCount(Long courseId, Long parentid) {
        LambdaQueryWrapper<Teachplan> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Teachplan::getCourseId, courseId);
        queryWrapper.eq(Teachplan::getParentid, parentid);
        Integer count = teachplanMapper.selectCount(queryWrapper);
        return count + 1;
    }
}
